package deptServer

import (
	"context"
	"devops-super/api"
	v1 "devops-super/api/clusters/v1"
	"devops-super/internal/consts"
	"devops-super/internal/dao"
	"devops-super/internal/model/do"
	"devops-super/internal/model/entity"
	"devops-super/internal/model/mymodel"
	"devops-super/internal/service"
	"devops-super/utility/util/arrayUtil"
	"errors"
)

type sDeptServer struct{}

func init() {
	service.RegisterDeptServer(New())
}

func New() *sDeptServer {
	return &sDeptServer{}
}

func (*sDeptServer) GetPageLst(ctx context.Context, in *v1.DeptServerPageLstReq) (out *api.PageLstRes[*mymodel.DeptServerResponse], err error) {
	out = &api.PageLstRes[*mymodel.DeptServerResponse]{}
	m := dao.AppDeptToServerRecord.Ctx(ctx).Safe(true)

	isSuperDept, currentUser, _ := service.User().IsCurrentUserSuperDept(ctx)
	if !isSuperDept {
		m = m.Where(dao.AppDeptToServerRecord.Columns().DeptId, currentUser.DeptId)
	}
	if in.DeptId > 0 {
		m = m.Where(dao.AppDeptToServerRecord.Columns().DeptId, in.DeptId)
	}
	if in.ServerKey != "" {
		m = m.Where(dao.AppDeptToServerRecord.Columns().ServerKey, in.ServerKey)
	}
	if in.Type != "" {
		m = m.Where(dao.AppDeptToServerRecord.Columns().Type, in.Type)
	}
	if err = m.Offset(in.Offset()).Limit(in.Limit()).ScanAndCount(&out.List, &out.Total, false); err != nil {
		return
	}

	deptIds := make([]int64, 0)
	for _, item := range out.List {
		if !arrayUtil.IsExistsItem(item.DeptId, deptIds) {
			deptIds = append(deptIds, int64(item.DeptId))
		}
	}
	var deptResults []*entity.Dept
	_ = dao.Dept.Ctx(ctx).WhereIn(dao.Dept.Columns().Id, deptIds).Scan(&deptResults)

	for index, e := range out.List {
		deptName := ""
		for _, d := range deptResults {
			if d.Id == int(e.DeptId) {
				deptName = d.Name
			}
		}
		out.List[index].DeptName = deptName
	}

	return
}

func (*sDeptServer) Add(ctx context.Context, in *entity.AppDeptToServerRecord) (err error) {
	cols := dao.AppDeptToServerRecord.Columns()
	count, _ := dao.AppDeptToServerRecord.Ctx(ctx).
		Where(cols.DeptId, in.DeptId).
		Where(cols.Type, in.Type).Count()
	if count > 0 {
		err = errors.New("already allocate this type to this department")
		return
	}

	count2, _ := dao.AppDeptToServerRecord.Ctx(ctx).
		Where(cols.ServerKey, in.ServerKey).Where(cols.Type, in.Type).Count()
	// 数据库和oss都必须严格隔离，mqtt不需要
	if in.Type == consts.ClusterTypeDatabase || in.Type == consts.ClusterTypeOss {
		if count2 > 0 {
			err = errors.New("already In Use By other department for This ServerKey-This Type  ")
			return
		}
	}

	count3, _ := dao.AppDeptToServerRecord.Ctx(ctx).
		Where(cols.DeptId, in.DeptId).
		Where(cols.ServerKey, in.ServerKey).
		Where(cols.Type, in.Type).Count()
	if count3 > 0 {
		err = errors.New("already exists")
		return
	}

	//防止越权
	isSuperDept, _, _ := service.User().IsCurrentUserSuperDept(ctx)
	if !isSuperDept {
		err = errors.New("permission denied")
		return
	}

	insert := do.AppDeptToServerRecord{
		DeptId:    in.DeptId,
		ServerKey: in.ServerKey,
		Type:      in.Type,
		Remark:    in.Remark,
		CreatedAt: in.CreatedAt,
		UpdatedAt: nil,
	}
	_, err = dao.AppDeptToServerRecord.Ctx(ctx).Insert(insert)
	return
}

func (*sDeptServer) Del(ctx context.Context, req *v1.DeptServerDelReq) (err error) {

	//是否有设备占用
	var old *entity.AppDeptToServerRecord
	err = dao.AppDeptToServerRecord.Ctx(ctx).WherePri(req.Id).Scan(&old)
	if err != nil || old.Id == 0 {
		return
	}
	if old.Type == consts.ClusterTypeDatabase {
		count, _ := dao.AppDevice.Ctx(ctx).Where(dao.AppDevice.Columns().DatabaseServer, old.ServerKey).Count()
		if count > 0 {
			err = errors.New("is in use by some device,cannot delete")
			return
		}
	}
	if old.Type == consts.ClusterTypeMqtt {
		count, _ := dao.AppDevice.Ctx(ctx).Where(dao.AppDevice.Columns().MqttServer, old.ServerKey).Count()
		if count > 0 {
			err = errors.New("is in use by some device,cannot delete")
			return
		}
	}
	if old.Type == consts.ClusterTypeOss {
		count, _ := dao.AppDevice.Ctx(ctx).Where(dao.AppDevice.Columns().OssServer, old.ServerKey).Count()
		if count > 0 {
			err = errors.New("is in use by some device,cannot delete")
			return
		}
	}
	//防止越权
	isSuperDept, _, _ := service.User().IsCurrentUserSuperDept(ctx)
	if !isSuperDept {
		err = errors.New("permission denied")
		return
	}
	_, err = dao.AppDeptToServerRecord.Ctx(ctx).WherePri(req.Id).Delete()
	return
}
